/*
 * BeanNameUtils.java Copyright YaZuo Tech Co. Ltd. All Rights
 * Reserved.
 */
package com.zs.framework.mail.utils;

import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.core.type.StandardMethodMetadata;

import java.lang.annotation.Annotation;
import java.util.Map;
import java.util.stream.Stream;

/**
 * Bean名称工具
 * 
 * @since 2020-07-23
 * @author zhougf
 *
 */
public class BeanNameUtils {

    /**
     * 使用指定类型注解获取Bean名
     * 
     * @param beanType
     * @param annotationType
     * @param applicationContext
     * @return
     *
     *         Stream<String>
     */
    public static <T> Stream<String> getBeanNamesByTypeWithAnnotation(Class<T> beanType,
            Class<? extends Annotation> annotationType, AbstractApplicationContext applicationContext) {
        return Stream.of(applicationContext.getBeanNamesForType(beanType)).filter(name -> {
            final BeanDefinition beanDefinition = applicationContext.getBeanFactory().getBeanDefinition(name);
            final Map<String, Object> beansWithAnnotation = applicationContext.getBeansWithAnnotation(annotationType);

            if (!beansWithAnnotation.isEmpty()) {
                return beansWithAnnotation.containsKey(name);
            } else if (beanDefinition.getSource() instanceof StandardMethodMetadata) {
                StandardMethodMetadata metadata = (StandardMethodMetadata) beanDefinition.getSource();
                return metadata.isAnnotated(annotationType.getName());
            }

            return false;
        });
    }

    /**
     * 使用注解获取Bean名
     * 
     * @param annotationType
     * @param applicationContext
     * @return
     *
     *         Stream<String>
     */
    public static <T> Stream<String> getBeanNamesByAnnotation(Class<? extends Annotation> annotationType,
            AbstractApplicationContext applicationContext) {
        return Stream.of(applicationContext.getBeanNamesForAnnotation(annotationType)).filter(name -> {
            final Map<String, Object> annotation = applicationContext.getBeansWithAnnotation(annotationType);

            if (!annotation.isEmpty()) {
                return annotation.containsKey(name);
            }

            return false;
        });
    }
}
